package cn.izeno.wx.models

import cn.izeno.wx.aes.WXBizMsgCrypt
import cn.izeno.wx.models.component.AppAuthParam
import cn.izeno.wx.models.component.AppTokenParam
import cn.izeno.wx.models.component.FastCreateWeappInfo
import cn.izeno.wx.models.mp.KfMessageBuilder
import cn.izeno.wx.service.WX
import io.reactivex.rxjava3.schedulers.Schedulers
import org.simpleframework.xml.Element
import org.simpleframework.xml.core.Persister

/**
 * 微信公众号消息
 */
class AppMsg {
  @field:Element(name = "Encrypt", required = false)
  var encrypt: String = ""

  @field:Element(name = "MsgId", required = false)
  var id: String = ""

  @field:Element(name = "ToUserName", required = false)
  var toUserName: String = ""

  @field:Element(name = "FromUserName", required = false)
  var fromUserName: String = ""

  @field:Element(name = "CreateTime", required = false)
  var createdAt: String = ""

  @field:Element(name = "MsgType", required = false)
  var type: String = ""

  //  文本消息
  @field:Element(name = "Content", required = false)
  var content: String = ""

  //<editor-fold desc="媒体消息">
  @field:Element(name = "MediaId", required = false)
  var mdediaId: String = ""

  // 视频消息会有主图
  @field:Element(name = "ThumbMediaId", required = false)
  var thumbMediaId: String = ""

  @field:Element(name = "Format", required = false)
  var format: String = ""

  @field:Element(name = "Recognition", required = false)
  var recognition: String = ""

  @field:Element(name = "PicUrl", required = false)
  var picUrl: String = ""

  @field:Element(name = "Title", required = false)
  var title: String = ""

  @field:Element(name = "Description", required = false)
  var description: String = ""

  @field:Element(name = "Url", required = false)
  var url: String = ""
  //</editor-fold>

  @field:Element(name = "Event", required = false)
  var event: String = ""

  @field:Element(name = "MenuId", required = false)
  var menuId: String = ""

  @field:Element(name = "EventKey", required = false)
  var eventKey: String = ""

  //<editor-fold desc="位置上报事件">
  @field:Element(name = "Latitude", required = false)
  var latitude: Float = 0F

  @field:Element(name = "Longitude", required = false)
  var longitude: Float = 0F

  @field:Element(name = "Precision", required = false)
  var precision: Float = 0F
  //</editor-fold>

  @field:Element(name = "Ticket", required = false)
  var ticket: String = ""

  @field:Element(name = "Status", required = false)
  var status: String = ""


  //<editor-fold desc="小程序事件相关字段">
  /** [WEAPP_AUDIT_SUCCESS] */
  @field:Element(name = "SuccessTime", required = false)
  var successTime: Long = 0
    set(value) {
      field = if (value < 9999999999) {
        value * 1000
      } else {
        value
      }
    }

  /** [WEAPP_AUDIT_FAIL] */
  @field:Element(name = "FailTime", required = false)
  var failTime: Long = 0
    set(value) {
      field = if (value < 9999999999) {
        value * 1000
      } else {
        value
      }
    }

  /** [WEAPP_AUDIT_FAIL] 审核失败的原因 */
  @field:Element(name = "Reason", required = false)
  var reason: String? = null

  /**
   * [WEAPP_AUDIT_FAIL] ScreenShot 审核失败的小程序截图示例 （xxx yyy zzz是图片media_id，可通过
   * [获取永久素材接口](https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738730)
   * 拉取截图内容）
   */
  @field:Element(name = "ScreenShot", required = false)
  var screeShoot: String? = null


  //</editor-fold>


  companion object {

    /**
     * 小程序审核通过
     */
    const val WEAPP_AUDIT_SUCCESS = "weapp_audit_success"

    /**
     * 小程序审核不通过
     */
    const val WEAPP_AUDIT_FAIL = "weapp_audit_fail"

    const val MP_EVENT_SUBSCRIBE = "subscribe"       //关注
    const val MP_EVENT_UNSUBSCRIBE = "unsubscribe"   //取关
    const val MP_EVENT_SCAN = "SCAN"                 //扫描二维码


    private val parser: Persister by lazy { Persister() }

    fun parse(msgCrypt: WXBizMsgCrypt, body: String, sign: String, timestamp: String, nonce: String): AppMsg {
      val encrypt = parser.read(AppMsg::class.java, body).encrypt
      val dec = msgCrypt.verifyUrl(sign, timestamp, nonce, encrypt)
      return parser.read(AppMsg::class.java, dec)
    }

    /**
     * 审核助手
     * @return 字符串为空不处理，不为空直接返回
     */
    fun verifyHelper(wxCrypt: WXBizMsgCrypt, msg: AppMsg, timestamp: String, nonce: String): String {
      if (msg.content == "TESTCOMPONENT_MSG_TYPE_TEXT") {
        val msgBack = TextMessage()
        msgBack.content = "TESTCOMPONENT_MSG_TYPE_TEXT_callback"
        msgBack.fromUserName = msg.toUserName
        msgBack.toUserName = msg.fromUserName
        return wxCrypt.encryptMsg(msgBack.toXMLString(), timestamp, nonce)
      }

      if (msg.content.contains("QUERY_AUTH_CODE:")) {
        handlerVerify(msg.content.replace("QUERY_AUTH_CODE:", ""), msg.fromUserName)
        return "success"
      }

      return ""
    }

    private fun handlerVerify(code: String, openid: String) {
      WX.open.accessToken(AppAuthParam(code))
          .observeOn(Schedulers.newThread())
          .flatMap { WX.open.authToken(AppTokenParam(it.appid, it.refreshToken)) }
          .flatMap {
            val msg = KfMessageBuilder(it.accessToken).toUser(openid).text("${code}_from_api")

            WX.customer.sendMessage(msg)
          }
          .subscribe({
            print("success")
          }, { it.printStackTrace() })
    }
  }
}
